import os
from io import BytesIO
import PIL
from openpyxl import Workbook
from openpyxl.drawing.image import Image as XLImage
from openpyxl.utils import get_column_letter
from semantic_nav.utils import image_to_bytes
from semantic_nav.log_utils import get_logger
logger = get_logger()


def save_image_in_excel(worksheet, img, row, column):
    """
    Save the image to a specific cell in the excel workbook.

    Parameters:
        worksheet (openpyxl.worksheet.worksheet.Worksheet): excel worksheet to operate on
        img (PIL.Image.Image or BytesIO): the image to be saved
        row (int): the row number where the image should be saved
        column (int): the column number where the image should be saved

    Returns:
        None
    
    Exceptions:
        if the image fails to save, an exception will be raised.
    """
    xl_img = XLImage(img)
    cell = worksheet.cell(row=row, column=column)
    worksheet.add_image(xl_img, cell.coordinate)


def save_images_and_text_to_excel(headers, data, output_file_path):
    """
    Save a list of headers and data to an Excel file, with images added to specific cells.

    Parameters:
        headers (list): A list of strings representing the headers for the Excel file.
        data (list of lists): A nested list where each inner list contains the data for a row.
                              Images should be represented as PIL.Image.Image objects.
        output_file_path (str): The file path where the Excel file will be saved.

    Returns:
        None: This function does not return a value.
    
    Exceptions:
        If the length of 'data' does not match the length of 'headers', the function will exit early.
        The Excel file will be saved to the specified output file path.
    """
    if len(data) > 0 and len(headers) != len(data[0]):
        return

    wb = Workbook()
    ws = wb.active
    ws.title = "Images and Text"

    # Add headers to the first row
    for col, header in enumerate(headers, start=1):
        ws.cell(row=1, column=col, value=header)
        ws.column_dimensions[get_column_letter(col)].width = 50

    # Add data to the rest of the rows
    for row, row_data in enumerate(data, start=2):
        for col, cell_data in enumerate(row_data, start=1):
            ws.row_dimensions[row].height = 200
            if isinstance(cell_data, PIL.Image.Image):
                save_image_in_excel(ws, BytesIO(image_to_bytes(cell_data)), row, col)
            else:
                ws.cell(row=row, column=col, value=cell_data)

    # Save the excel file
    wb.save(output_file_path)
    logger.info(f"Excel file saved to {output_file_path}")
